Декомпозиция и абстракция

Жизненный цикл программы

ЖЦ - является моделью создания и использования программного обеспечения (ПО), отражающей его различные состояния, начиная с момента возникновения необходимости в данном программном изделии и заканчивая моментом его полного выхода из употребления у всех пользователей.

Анализ требований - первая фаза разработки ПО, на которой требования заказчика уточняются, формализуются и документируются. На этом этапе даётся ответ на вопрос: “Что должна делать будущая система?”.

Разработка - вторая фаза разработки ПО, которая даёт ответ на вопрос: “Каким образом система будет удовлетворять предъявленным к ней требованиям?”.

Тестирование - третья фаза разработки ПО, на которой осуществляется тестирование и отладка ПО.

Эксплуатация - четвёртая фаза разработки ПО, на которой осуществляется сопровождение и модификация ПО.

Технология программирования - система методов принципов и средств автоматизации, обеспечивающих в заданных условиях получение программной продукции с заданными свойствами.

Декомпозиция

Декомпозиция - процесс разделения сложной задачи на множество меньших независимых задач, лёгких для понимания и решения.

Детализация - привлечение в рассмотрение существенной для решаемой задачи информации.

Абстрактное понятие - понятие, в котором мыслится свойство предмета или отношения между предметами.

Иерархия - порядок подчинения низших чинов высшим чинам.

Цель процесса декомпозиции - на основе детализации расчленить исходную задачу на части, которые представляют собой выбранные абстракции, и построить схему иерархии полученных абстракций.

Набор абстракций определяет выбранная технология программирования. Так технология на основе абстрактных типов данных предлагает описывать задачу в терминах абстракций данных, для описания которых, в свою очередь, используются абстракции через параметризацию, абстракции через спецификацию, абстракции итерации, процедурные абстракции.

При декомпозиции задачи мы разбиваем её на ряд подзадач так, чтобы

• каждая подзадача имела один и тот же уровень детализации;

• каждая подзадача могла быть решена независимо,

• полученные решения, будучи объединены вместе, позволяли решить исходную проблему.

Декомпозиция задачи требует вовлечения в рассмотрение деталей, особенностей процесса обработки данных, исполняемого при решении задачи.

Правильно выбранный уровень детализации позволяет сформировать абстракции следующего уровня, абстрагированием от введённых деталей.

На начальном этапе решения задачи уровень абстрагирования - наивысший, уровень детализации - низший.

Конечный этап решения задачи характеризуется низшим уровнем абстрагирования и наивысшим уровнем детализации.

Абстракция представляет собой эффективный способ декомпозиции, осуществляемый посредством изменения списка детализации. Когда мы абстрагируемся от проблемы мы предполагаем игнорирование ряда подробностей с тем, чтобы свести задачу к более простой.

Последовательное выполнение декомпозиции посредством детализации и последующего абстрагирования выполняется при проектировании до тех пор, пока исходная проблема не будет сведена к набору подзадач, решение которых известно.

Абстракция

Понятие - форма мышления, отражающая предметы в их существенных признаках.

Содержание понятия - совокупность существенных признаков предмета, которая мыслится в данном понятии.

Объём понятия - совокупность предметов, которая мыслится в понятии.

Термин - это слово или словосочетание, обозначающее строго определённое понятие в пределах данной науки или группы родственных наук.

Конкретное понятие - понятие, в котором мыслится предмет или совокупность предметов как нечто самостоятельно существующее.

Абстрактное понятие - понятие, в котором мыслится свойство предмета или отношение между предметами.

Определение понятия - логическая операция, раскрывающая содержание понятия.

Процесс обработки данных - процесс последовательного изменения состояния данных в результате выполнения над ними заданных операций, цель которого - получение результирующего состояния данных из исходного.

Абстрагирование - мысленное выделение отдельных признаков предмета и отвлечение от других признаков называется абстрагированием.

Абстракция - понятия, используемые при проектировании программ.

Спецификация - форма (шаблон) в соответствии с которой, раскрывается содержание абстракции.

Реализации - процессы обработки данных, которые мыслятся в абстракции.

Любая программа есть описание процесса обработки данных, который будет реализовываться при её выполнении. Проектировщик мыслит программу в форме иерархии подходящих абстракций. Составление спецификации абстракции - есть описание поведения (существенных признаков) абстракции в соответствии с выбранным шаблоном спецификации. Спецификация абстракции предполагает множество удовлетворяющих ей реализаций. В любом процессе обработки данных можно выделить две стороны: данные и операции, выполняемые над ними. Поэтому при описании процессов обработки данных используют абстракцию через параметризацию, абстракцию через спецификацию. Два этих вида абстракций применяют для построения процедурных абстракций, абстракций данных, абстракций итерации.

Процесс абстрагирования может быть рассмотрен как некоторое обобщение. Он позволяет нам забыть об информации и, следовательно, рассматривать различные предметы так, как если бы они были эквивалентны. Мы выполняем это в надежде упростить наш анализ, отделяя существенные атрибуты от не существенных.

Пример абстракции

Ниже приведена спецификация процедурной абстракции.


Таблица 1 - Спецификация процедурной абстракции

Ниже приведены три реализации, удовлетворяющие выше приведённой:


пример реализации 1,
   Function Gcd(a,b:integer):integer;
   begin
	while a<>b do begin
		if a>b then b:= b-a else a:=a-b
	end;
	Gcd:= a
   end;
пример реализации 2,
   function Gcd(u,v:longint):longint;
   begin
     if v>u then begin v:=v+u;u:=v-u;v:=v-u end;
     while v<>0 do begin
       u:= u mod v;
       if v>u then begin v:=v+u;u:=v-u;v:=v-u end;
     end;
     Gcd:=u;
   end;
пример реализации 3.
   function Gcdr(u,v:longint):longint;
   begin
     if v>u then begin v:=v+u;u:=v-u;v:=v-u end;
     if v=0 
      then Gcdr:=u
     else Gcdr:=Gcdr(u mod v,v)
   end;

   Function Gcd(a,b:integer):integer;
    begin
	while a<>b do begin
		if a>b then b:= b-a else a:=a-b
	end;
	Gcd:= a
    end;

   function Gcd(u,v:longint):longint;
    begin
      if v>u then begin v:=v+u;u:=v-u;v:=v-u end;
      while v<>0 do begin
          u:= u mod v;
          if v>u then begin v:=v+u;u:=v-u;v:=v-u end;
     end;
     Gcd:=u;
   end;

   function Gcdr(u,v:longint):longint;
    begin
       if v>u then begin v:=v+u;u:=v-u;v:=v-u end;
       if v=0 
         then Gcdr:=u
       else Gcdr:=Gcdr(u mod v,v)
    end;


Абстракция через параметризацию

В абстракциях через параметризацию мы абстрагируемся от конкретных используемых данных. Эта абстракция определяется в терминах формальных параметров. Фактические данные связываются с этими параметрами в момент использования такой абстракции. Значения конкретных используемых данных являются несущественными; важно лишь их количество и типы. Параметризация позволяет обобщить процесс обработки данных, делая его полезным в большом числе ситуаций. Преимущество таких обобщений заключается в том, что они уменьшают объём программы и, следовательно, объём модификаций.

Пример. Пусть имеются следующие реализации процессов обработки данных:

2*2+6*6
5*5-8*8
4*4+9*9
5*5+7*7
3*3-5*5
7*7-9*9

Используя абстракцию через параметризацию все их можно обобщить, например, так:


function R(a,b:Integer):Integer
 int R(int a, int b)


Используя заголовок функции С++ или Паскаля, а он, по существу, и является спецификацией абстракции через параметризацию, мы акцентировали наше внимание на таких существенных признаках этих реализаций, как входные параметры, результат и их типах.

Абстракция через спецификацию

Абстракция через спецификацию фокусирует внимание на особенностях, от которых зависит пользователь, и пренебрегает особенностями реализации этих особенностей. Существенным является поведение - то, что делается, а несущественным - то, как это делается.

Локальность предполагает, что каждая реализация может быть рассмотрена независимо от остальных. Абстракция может быть использована без уяснения для себя способа её реализации и реализована без понимания того, как она будет использована.

Модифицируемость означает, что одна реализация может быть заменена другой без изменения других программ, если новая реализация удовлетворяет той же спецификации.

Главное преимущество абстракции через спецификацию заключается в не существенности способа реализации, что позволяет нам переходить к другой реализации без внесения изменений в программу, использующую данную реализацию. Абстракция через спецификацию наделяет структуру программы двумя отличительными особенностями. Первая из этих особенностей заключается в локальности. Второй особенностью является модифицируемость.

Пример. Пусть имеются следующие реализации процессов обработки данных:

1) 2*2 + 2*2*6 + 6*6
2) 5*5 - 8*8
3) 4*4 + 2*4*9 + 9*9
4) 5*5 + 2*5*7 + 7*7
5) 3*3 - 5*5
6) 7*7 - 9*9

Используя абстракцию через спецификацию можно обобщить представленные реализации, например, так:

1, 3, 4 реализации - квадрат суммы (a +b) 2,

2, 5, 6 реализации - разность квадратов (a2 –b2).

Здесь мы акцентировали наше внимание на таких существенных признаках этих реализаций, как связь входных параметров с результатом.

Спецификация

Спецификация раскрывает содержание абстракции (её поведение), фокусирует внимание на особенностях, от которых зависит пользователь.

Язык спецификаций - язык, на котором пишутся спецификации.

Очень важно дать абстракции чёткое определение. Определяют абстракции посредством спецификаций, которые создаются на языке спецификаций. Язык спецификаций может быть формальным и не формальным. Преимущество формальных спецификаций состоит в том, что они имеют точно определённое значение. Неформальные спецификации легче читать и понимать, однако точное их содержание установить затруднительно, поскольку язык неформальных спецификаций точным не является. Спецификация отлична от любой определяемой ею реализации абстракции (см. Пример.). Все реализации сходны между собой, поскольку они реализуют одну и ту же абстракцию. Они отличаются тем, что делают это разными способами. Спецификация определяет их схожесть.


Процедурная абстракция

Спецификации процедурных абстракций

Шаблон спецификации определяет форму и набор существенных признаков поведения абстракции, которые необходимо определить.

Спецификация процедуры состоит из заголовка и описания функции.

Описание функции (семантическая часть спецификации) состоит из трёх разделов - предусловия, постусловия, процесс.

Язык спецификаций - язык, на котором пишутся спецификации.

Реализация процедурной абстракции есть процедура или функция, которая отображает набор значений входных аргументов в выходной набор результатов, с возможной модификацией входных значений. Эти особенности поведения процедурной абстракции и должны быть описаны в спецификации. Её шаблон имеет следующий вид (таблица 2)


Таблица 2 – Шаблон процедурной абстракции

Имя

Имя процедурной абстракции

Вход:

имена и типы исходных данных

Предусловия:

Ограничение на абстракцию

Процесс:

выполняемая функция

Выход:

тип возвращаемого результата

Постусловия:

возможные модификации исходных данных


Заголовок содержит три раздела: «Имя», «Вход», «Выход».

«Имя» содержит имя процедуры; «Вход» содержит порядок и типы входных параметров; «Выход» содержит выходные параметры. Выходные параметры могут, а входные параметры должны быть поименованы.

Семантическая часть спецификации состоит из трёх разделов – «Предусловия», «Постусловия», «Процесс».

Эти разделы появляются в указанном порядке, однако разделы «Предусловия» и «Постусловия» обязательными не являются.

Предложение «Предусловия» задаёт ограничение на абстракцию. Оно необходимо, если поведение абстракции не определено для некоторых входных значений. Для глобальных процедур оно может быть опущено.

Предложение «Постусловия» задаёт список имён входных параметров, модифицируемых процедурой. При отсутствии входных параметров оно может быть опущено.

Предложение «Процесс» определяет выходные значения и модификации, производимые над входными параметрами, перечисленными в списке «Постусловия». Оно составляется, исходя из предположения, что требования в предложении «Предусловия» удовлетворены, в противном случае о поведении процедуры ничего не сообщается. Ниже приводится несколько спецификаций (таблицы 3,4,5).


Таблица 3- Пример 1

Имя

BinarySerch(Поиск)

Вход:

a – одномерный массив целых, x – целое число

Предусловия:

Элементы массива a упорядочены в порядке возрастания

Процесс:

Если x принадлежит а, то возвращается i, такое, что a[i] = x; в противном случае возвращается high(a)+1

Выход:

целое значение

Постусловия:

Нет


Таблица 4 – Пример 2

Имя

Swap(Перестановка)

Вход:

x, y – целые переменные

Предусловия:

Нет

Процесс:

По возвращению из процедуры переменные x,y обмениваются значениями т.е. Xpost = Y, Ypost=X

Выход:

Нет

Постусловия:

Модифицируются x и y


Таблица 5 -Пример 3

Имя

Concat(Слияние)

Вход:

x, y – строки

Предусловия:

Нет

Процесс:

По возврату xy есть новая строка, содержащая символы из x (в том порядке, в котором они расположены в x), за которыми следуют символы из y (в том порядке, в котором они расположены в y)

Выход:

Строка xy

Постусловия:

Нет


Процедуры concat, swap являются общими процедурами, поскольку их спецификации не содержат предусловий. Прцедура BinarySearch является частичной, она выполняет свои функции в том случае, если входной массив отсортирован.

Реализация процедурных абстракций

Реализация процедуры должна выполнять действие, определённые в спецификации. В частности, она должна модифицировать только те входные параметры, которые указаны в в разделе «Постусловия», а условия в разделе «Предусловия»должны выполняться для всех входных значений. Выходные значения должны соответствовать требованиям, указанным в разделе «Процесс».

Каждый язык программирования имеет свой механизм реализации процедурных абстракций.

Ниже показаны функции, написанные на Турбо Паскале и реализующие абстракции Search и Swap. Searcha, Searchb и Swapa, Swapb являются допустимыми реализациями, потому что удовлетворяют соответствующим им абстракциям.


function Searcha(const a:array of Integer; x:Integer):integer;
var i:integer;
begin
  for i:= Low(a) to High(a) do begin
    if a[i] = x then begin searcha:= i; exit end
  end;
  searcha:= High(a)+1
end;
function Searchb(const a:array of Integer; x:Integer):integer;
var i:integer;lo,hi,mid,val:integer;
begin
  lo:=Low(a); hi:=High(a);
  while lo < hi do begin
    mid:=(Lo+hi) div 2;
    val:= a[mid];
    if x < val then hi:= mid - 1
      else if x = val then begin searchb:= mid; exit end
              else lo:= mid+1;
  end;
  searchb:=hi+1;
end;
procedure Swapa(x,y:Integer);
var t:integer;
begin
   t:=x; x:=y; y:=x
end;
procedure Swapb(x,y:Integer);
begin
   x:=x+y; y:=x-y; x:=x-y
end;


Параметризация процедурных абстракций

Возможно дальнейшее обобщение процедурной абстракции, расширяя её через параметризацию и используя типы данных в качестве параметров. При использовании типов в качестве параметров некоторые значения параметров могут не иметь смысла. Например, массивы могут быть отсортированы только в том случае, если элементы, принадлежащие к типу, упорядочены. Ограничения на параметры типа предполагают набор некоторых заданных операций над ними. Спецификация абстракции должна содержать эти ограничения в предложении requires. Ниже приведена спецификация параметризованной процедурной абстракции.

Sort = proc [t:type] (a: array[t]) returns(array[t])

requires t имеет

lt: proctype(t,t ) returns(bool)

которая упорядочивает t.

modifies a

effects Возвращает новый массив с тем же числом элементов, что и а, и содержащий элементы а, расположенные в возрастающем порядке; порядок устанавливается через операцию lt.

Создание процедурных абстракций

Мы заинтересованы в разработке и реализации хороших абстракций. Поэтому, желательно, чтобы процедуры обладали такими свойствами, как минимальность, простота и обобщённость. Минимальность состоит в том, что в процедуре должны быть реализованы только необходимые функции. Это предоставляет разработчику большую свободу, позволяя ему создать более эффективную версию. Например, если процедурная абстракция sort сортировки массива позволяет модифицировать аргумент, заданный массивом, то это уменьшает занимаемый ею объём памяти. Однако список значимых подробностей такого рода должен быть ограничен.

Так, обычно остаётся неопределённым сам метод, используемый в конкретной реализации. Так же могут быть оставлены неопределёнными некоторые выполняемые процедурой функции. В такой ситуации процедура становится не доопределенной. Это означает, что для определённых значений входных параметров на выходе вместо правильного единственного результата имеется набор допустимых результатов. Реализация может ограничить этот набор одним значением, однако он может быть любым из числа допустимых.

Процедура search является не доопределенной, поскольку мы не указываем точно, какой индекс должен быть возвращён в том случае, если значение x встречается в массиве несколько раз.

Другим важным свойством является обобщённость, которая достигается использованием параметров вместо переменных. Например, процедура, работающая с массивами произвольного размера, является более обобщённой, чем та, которая работает с массивами фиксированного размера.

Другой важной характеристикой процедуры является простота. Процедура должна обладать хорошо определённым и легко объяснимым назначением, независимым от контекста её использования. Хорошим правилом может служить присваивание процедуре имени, описывающим её значение.

Процедуры могут быть частными и общими (глобальными). Частные процедуры не так безопасны, как общие, поскольку они требуют от пользователя выполнения требований, заданных в разделе «Предусловия». Если эти требования не удовлетворены, то поведение процедуры становится неопределённым, что может привести к неверной работе программы.

С другой стороны, частичные процедуры могут оказаться более эффективными, чем общие.

При выборе между частной и общей процедурами мы должны придерживаться определённых соглашений. С одной стороны, критерием должна являться эффективность. С другой - корректное выполнение с меньшим числом ошибок. Каким образом осуществить такой выбор? Одним из важных факторов является ожидаемая область применения, Если процедура создаётся для общего пользования (например, доступна как часть библиотеки программ), то соображения безопасности играют существенную роль.

Другой случай предполагает использование процедуры в ограниченном контексте. В ограниченном контексте легче обеспечить выполнение необходимых требований:

Минимальность

Минимальность состоит в том, что в процедуре должны быть реализованы только необходимые функции. Это предоставляет разработчику большую свободу, позволяя ему создать более эффективную версию. Например, если процедурная абстракция sort сортировки массива позволяет модифицировать аргумент, заданный массивом, то это уменьшает занимаемый ею объём памяти. Однако список значимых подробностей такого рода должен быть ограничен.

Обобщенность

Другим важным свойством является обобщённость, которая достигается использованием параметров вместо переменных. Например, процедура, работающая с массивами произвольного размера, является более обобщённой, чем та, которая работает с массивами фиксированного размера. Аналогично процедура, работающая с массивами элементов произвольного типа, является более обобщенной, чем процедура, требующая, чтобы все элементы массива были целыми числами. Однако обобщение процедуры полезно, если эффективность её применения повышается. Это почти всегда так, когда речь идёт о независимости от размеров.

Простота

Другой важной характеристикой процедуры является простота. Процедура должна обладать хорошо определённым и легко объяснимым назначением, независимым от контекста её использования. Хорошим правилом может служить присваивание процедуре имени, описывающим её значение. Процедура должна действительно выполнять некоторые функции. Процедуры создаются в процессе написания программ и служат цели упрощения и облегчения работы с ней, а также создания более ясной структуры программы. При этом программа становится легко понимаемой. Однако существует опасность введения слишком большого числа процедур.

Недоопределённость

Стремление к минимизации процедурной абстракции приводит к не доопределённости процедур.

Обычно остаётся неопределённым сам метод, используемый в конкретной реализации. Так же могут быть оставлены неопределёнными некоторые выполняемые процедурой функции. В такой ситуации процедура становится не доопределенной. Это означает, что для определённых значений входных параметров на выходе вместо правильного единственного результата имеется набор допустимых результатов. Реализация может ограничить этот набор одним значением, однако он может быть любым из числа допустимых.

Процедура search является не доопределенной, поскольку мы не указываем точно, какой индекс должен быть возвращён в том случае, если значение x встречается в массиве несколько раз.

Частные и общие процедуры

Процедуры могут быть частными и общими (глобальными). Частные процедуры не так безопасны, как общие, поскольку они требуют от пользователя выполнения требований, заданных в предложении requires. Если эти требования не удовлетворены, то поведение процедуры становится неопределённым, что может привести к неверной работе программы.

С другой стороны, частичные процедуры могут оказаться более эффективными, чем общие.

При выборе между частной и общей процедурами мы должны придерживаться определённых соглашений. С одной стороны, критерием должна являться эффективность. С другой - корректное выполнение с меньшим числом ошибок. Каким образом осуществить такой выбор? Одним из важных факторов является ожидаемая область применения, Если процедура создаётся для общего пользования (например, доступна как часть библиотеки программ), то соображения безопасности играют существенную роль.

Другой случай предполагает использование процедуры в ограниченном контексте. В ограниченном контексте легче обеспечить выполнение необходимых требований.


Абстракции данных

Преимущества абстракций данных

Абстракция данных - средство описания процесса обработки данных, для которого существенным являются объекты и определённые на них операции.

Абстракции данных обеспечивают возможность расширения языка программирования новыми типами данных. Новые типы данных должны включать в себя абстракции, как через параметризацию, так и через спецификацию. Абстракция через параметризацию может быть осуществлена точно так же, как и для процедур, - использованием параметров там, где это имеет смысл. Абстракция через спецификацию достигается за счет того, что мы представляем операции как часть типа. Абстракции данных - наиболее важный метод в проектировании программ они позволяют отложить окончательный выбор структур данных до момента, когда эти структуры станут нам достаточно ясны.

Спецификации абстракций данных

Заголовок - обязательный раздел спецификации абстракции данных, определяющий имя типа и имена его операций.

Секция описания - обязательный раздел спецификации абстракции данных, в нём тип описывается как целое.

Секция операций - обязательный раздел спецификации абстракции данных, в нём содержатся спецификации для всех операций.

Значение абстрактного типа данных определяется его спецификацией. Спецификация абстракции данных состоит из:

- заголовка, определяющего имя типа и имена его операций,

- секции описания,

- секции операций.

В секции описания тип описывается как целое. Иногда там дается модель для объектов, т.е. объекты, описываются в терминах других объектов - таких, которые по предположению понятны тем, для кого эта спецификация предназначена. В секции описания так же говорится, изменяемый или неизменяемый это тип.

В секции операций содержатся спецификации для всех операций. Если операция - процедура, то её спецификация будет процедурной спецификацией. Операция так же может быть абстракцией через итерацию. В этих спецификациях могут использоваться концепции, введенные в секции описания.

Ниже представлена спецификация абстракции данных intset (таблица 6). Наборы целых чисел intset -это неограниченные множества целых чисел с операциями создания нового, пустого набора, проверки данного целого числа на принадлежность данному набору intset и добавления или удаления элементов. Заметим, что в секции описания мы описали наборы целых чисел в терминах математических множеств. Там же мы отметили, что наборы целых чисел - изменяемые, и перечислили все изменяющие операции. В секции операций мы задали каждую операцию в терминах математических множеств. Заметим, что спецификации операций insert, delete используют обозначение spost, что указывает на значение s при возврате из операции. Имя входного аргумента без квалификатора post всегда обозначает значение при вызове операции.

intset = data type is create,insert,delete,member,size,choose

Описание

Наборы целых чисел intset - неограниченные математические множества целых чисел.

Множества целых чисел изменяемые: операции insert, delete добавляют и уничтожают целые числа из множества

Операции

Таблица 6 - Спецификация абстракции данных intset

create

Начальные значения:

Нет

Процесс:

Возвращает новый пустой набор intset.

insert:

Вход:

S:intset,x:int.

Предусловия:

Нет

Процесс:

Добавляет x к элементам S, если такого элемента нет во множестве; после добавления - возврат, Spost = S U {x}.

Выход:

Нет

Постусловия:

S содержит элемент x.

delete:

Вход:

S:intset,x:int.

Предусловия:

Нет

Процесс:

Удаляет x из S; т.е., Spost = S - {x}.

Выход:

Нет

Постусловия:

S не содержит элемент x.

member:

Вход:

S:intset,x:int.

Предусловия:

Нет

Процесс:

Возвращает значение True, если x S, False – в противном случае.

Выход:

Р-ичное число (тип TPNumber).

Постусловия:

Нет.

size:

Вход:

S:intset,x:int.

Предусловия:

Нет

Процесс:

Возвращает число элементов в S.

Выход:

целое число

Постусловия:

Нет.

choose:

Вход:

S:intset

Предусловия:

набор S не пуст.

Процесс:

Возвращает произвольный элемент S.

Выход:

значение типа int.

Постусловия:

Нет.

end intset


Реализация абстракций данных

Тип представления - тип, выбранный для представления объектов абстрактного типа данных при их реализации.

Для реализации типа данных мы выбираем представление для объектов типа и реализуем операции в терминах этого представления. Выбранный тип представления должен предоставлять возможность простой и эффективной реализации всех операций. Кроме того, если некоторые операции должны выполняться быстро, представление должно предоставлять и эту возможность. Часто представление, обеспечивающее быструю работу некоторых операций, приводит к тому, что другие операции выполняются медленно. В этом случае мы должны использовать несколько различных операций одного и того же типа.

Каждая реализация абстракции данных будет иметь два типа: абстрактный тип и тип представления. Предполагается, что с типом представления мы имеем дело только при реализации. Всё, что мы можем делать с объектами абстрактного типа, - это применять к ним соответствующие данному типу операции.

Параметризация абстракций данных

Типы - выгодные параметры для типов, точно так же, как и для процедур. Например, рассмотрим абстракцию общего набора set, в котором элементы набора могут быть произвольного типа.

set = data type [t:type] is create,insert,delete,member,size,choose

Requires t имеет операцию

equal: proctype [t,t] returns(bool)

т.е. условие равенства t

Описание

Общие наборы set - неограниченные математические множества.

Эти множества изменяемые: операции insert, delete добавляют и уничтожают элементы множества

create = proc() returns(set[t])

effects Возвращает новый пустой набор.

insert = proc(S:set[t],x:t)

modifies S

effects Добавляет x к элементам S; после добавления - возврат, Spost = S U {x}.

delete = proc(S:set[t],x:t)

modifies S

effects Удаляет x из S; т.е., Spost = S - {x}.

member = proc(S:set[t],x:t) return (Bool)

effects Возвращает значение True, если x S.

size = proc(S:set[t]) return (t)

effects Возвращает число элементов в S.

choose = proc(S:set[t]) return (t)

requires набор S не пуст.

effects Возвращает произвольный элемент S.

Функция абстракции

Функция абстракции - функция, отображающая объекты представления в абстрактные объекты.

Функция абстракции и инвариант представления особенно полезны для понимания реализации абстракции данных. Они должны включаться в реализацию как комментарии. Функция абстракции данных определяет, каким образом объекты представления реализуют абстрактные объекты. Предполагается, что определённые объекты представления будут соответствовать определённым абстрактным объектам.

Для определения функции абстракции необходимо определить типичный элемент абстрактного типа.

Инвариант представления

Инвариант представления - условие, которому удовлетворяют все законные объекты.

Не все объекты представления являются законными представлениями абстрактных объектов. Условие, которому удовлетворяют все законные объекты представления, называется инвариантом представления.

Инвариант представления - это инвариант потому, что он всегда сохраняется для абстрактных объектов, т.е. он сохраняется, если объект используется вне его реализации. Инвариант представления не должен, однако, сохранятся всегда: он может быть, нарушен при выполнении одной из операций типа. Инвариант представления должен сохранятся при возврате из операций.

Свойства абстракций данных

Примитивный конструктор - операция, создающая объект соответствующего ей типа, не использующая никаких объектов в качестве аргумента, которым должны обладать реализации.

Конструктор - операция, использующая в качестве аргументов объекты соответствующего ей типа и создающая объекты того же типа.

Модификатор - операция, модифицирующая объекты соответствующего ей типа.

Наблюдатель - операция, использующая в качестве аргумента объект соответствующего ей типа и возвращающая результат другого типа.

Полнота - свойство типа данных, определяющее его способность обеспечить пользователя достаточным набором операций для выполнения необходимых работ с объектами с заданной эффективностью.


Абстракции итерации

Итератор

Абстракция итерации, или, коротко, итератор - это некоторый механизм, обеспечивающий доступ к компонентам объекта абстрактного типа данных.

Объект абстрактного типа данных - есть структурный объект, т.е. состоит из компонентов. При работе с ним нам необходим некоторый способ доступа к этим компонентам. Этот способ должен быть эффективным в смысле времени и пространства, удобным для использования и не должен разрушать объект. Кроме того, он должен обеспечивать абстракцию через спецификацию.

Итераторы являются тем механизмом, который решает эту задачу. Поскольку они выдают объекты по одному, не требуется дополнительного пространства для хранения объектов, и процедура может быть остановлена, когда нужный объект будет найден. Итераторы поддерживают абстракцию через спецификацию, инкапсулируя метод выдачи компонента. Этот метод зависит от знания представления этих объектов, но использующие его программы защищены от необходимости этого знания.

Спецификация абстракций итерации

Спецификация абстракции итерации - спецификация определяющая поведение итератора.

Форма спецификации итерации аналогична форме для процедуры. Заголовок имеет такой вид:

Iname = iter(...) yields(...) signals(...)

Здесь мы используем ключевое слово iter для обозначения абстракции итератора. Итератор может совсем не выдавать объектов на каждой итерации или выдавать несколько объектов. Число и тип этих объектов описывается в предложении yields. (Если для каждого yields не выдаётся ни одного объекта, то предложение yields может быть опущено.) Итератор может не выдавать никаких результатов, когда он заканчивается нормально, но он может заканчиваться по исключительной ситуации с именем и результатами, указанными в предложении signals. Например,

elements = iter(s:intset) yields(int)

requires s не модифицируется в теле цикла.

Effects Выдаёт элементы s, в некотором произвольном порядке, причём каждый элемент только один раз.

Вопросы проектирования абстракций итерации

Итераторы будут включаться среди других операций в большинство типов данных, особенно в такие, чьи объекты являются совокупностями других объектов. Итераторы часто необходимы для полноты - они позволяют организовать доступ к элементам некоторой совокупности таким способом, который эффективен и удобен.

Тип может иметь несколько итераторов.

Для изменяемых объектов мы требуем, чтобы объект, по которому происходит итерация, не изменялся в теле цикла.


Спецификации

Назначение спецификации

Абстракция (абстрактное понятие) - понятие, в котором мыслится свойство предмета или отношения между предметами.

Спецификация - форма, предназначенная для отображения содержания абстракции.

Реализация - один из мыслимых в абстракции предметов.

Назначение спецификации состоит в определении поведения абстракции. Пользователи полагаются на это поведение, а разработчики должны обеспечить его.

Реализация, обеспечивающая описываемое спецификацией поведение, удовлетворяет заданной спецификации.

Значение спецификации - это множество всех реализаций, удовлетворяющих ей.

Спецификации важны для достижения требуемой модульности программы. Абстракции используются для декомпозиции программы на модули. Без описания мы не можем понять, что собой представляет абстракция. Спецификация выступает в качестве такого описания.

Спецификация описывает соглашение между разработчиками и пользователями. Разработчик соглашается написать модуль, который относится к заданному множеству реализаций. Пользователь соглашается не полагаться на знание о том, какой именно член набора используется, т.е. не предполагать ничего такого, что не было бы указано в спецификации. Такое соглашение позволяет разделить анализ реализации от собственно использования программы.

Спецификации полезны и для документирования программы.

Создание спецификации концентрирует внимание на том, какой должна быть сама программа. Она служит как бы механизмом генерации вопросов, ответ на которые должен быть дан в результате консультации с пользователем, а не с разработчиком. Спецификация позволяет нам улучшить понимание требований к системе и проекту до начала их реализации.

Спецификации теряют значимость только в том случае, если становятся устаревшими соответствующие абстракции, то они эволюционируют до тех пор, пока эволюционирует сама абстракция.

Спецификации одинаково полезны разработчикам, проектировщикам и лицам, сопровождающим математическое обеспечение.

В процессе тестирования спецификации предоставляют информацию, которая может быть использована для генерации тестовых данных и построения заглушек, имитирующих работу данного модуля.

При обнаружении ошибки спецификации позволяют выявить их местоположение, Они определяют ограничения, которые необходимо соблюсти при исправлении ошибки. Спецификации весьма полезны в процессе сопровождения программного обеспечения. Существование ясной и аккуратной документации является необходимым условием для эффективного и успешного сопровождения.

Свойства спецификации

Обобщенность спецификации - свойство, позволяющее сократить число исключаемых, однако приемлемых реализаций.

Дефинитный стиль - такой стиль написания спецификаций, при котором явно перечисляются свойства, которым должны обладать реализации.

Операционный стиль - такой стиль написания спецификаций, при котором приводится способ конструирования реализаций.

Простота спецификации - свойство, определяющее понимаемость значения спецификации читателем.

Краткость спецификации - свойство, способное влиять на её простоту и состоящее в сокращении несущественной информации в спецификации.

Избыточность спецификации - свойство, способное влиять на её простоту и состоящее в разумном добавлении в спецификацию специальным образом излишней информации без повторений.

Структурированность спецификации - свойство, способное влиять на её простоту и состоящее в выделении избыточной информации специальным образом.

Хорошие спецификации могут иметь различные формы, однако все они имеют одинаковые атрибуты; к ним относятся: обобщенность, ограниченность, простота.

Хорошая спецификация должна быть достаточно ограничена. Имеется ряд распространенных ошибок, которые почти всегда приводят к неадекватно ограниченным абстракциям:

• неполное задание требований в разделе «Предусловия»;

• отсутствие полного списка исключительных ситуаций и поведения абстракции для граничных случаев.

Хорошая спецификация должна быть достаточно обобщенной.

Для получения достаточно обобщенной спецификации необходимо использовать дефинитный стиль для их написания. Операционный стиль приводит к недостаточно обобщенным спецификациям. Хорошей проверкой на обобщенность является анализ каждого требования спецификации в разделах «Предусловия», «Процесс» и уточнения их реальной необходимости.

При анализе спецификации необходимо рассмотреть не только свойства множества реализаций, но и свойства самой спецификации, насколько она удобна для чтения. Непонимание спецификации может иметь две формы: читатель, проанализировав спецификацию, приходит к выводу, что он не понимает её; читатель считает, что он понял спецификацию, а на самом деле он не понял её. Простота является важным свойством, оказывающим основное влияние на понятность спецификации. Имеется множество факторов, оказывающих влияние на простоту, среди которых: краткость, избыточность и структурированность являются, пожалуй, наиболее важными.

Краткое представление не всегда является наилучшим, однако на начальном этапе оно является лучшим. По мере возрастания объема спецификации возрастает вероятность появления в ней ошибок, а также появляется возможность её неверной трактовки.

Избыточность не должна присутствовать без серьезных причин и может быть оправдана в двух ситуациях: в случае если велика вероятность неправильного понимания спецификации, и в случае необходимости выявления ошибок. Избыточность вносится представлением информации несколькими способами без повторений. Вводимая избыточная информация помечается специальным способом. Избыточность не сокращает число ошибок в спецификации. Она делает их более очевидными и дает возможность читателю их обнаружить. При чтении читатель вносит свое представление о предмете, порождающее неоднозначность. Для её устранения может потребоваться введение весьма значительной избыточности.